#include "collect_config.h"
#include "json/json.h"
// #include "Enh_DataCollectConfig_Proxy.hpp"
#include "public_define.h"
#include "sys/stat.h"
#include "business_cacert_update.h"
#include "map_collect.h"
#include "yaml-cpp/yaml.h"

#include <iostream>
#include <fstream>
#include <filesystem>

using namespace std;
using namespace DcAdr;
// using ConfigProxy = com::changan::carDrive::dataCollect::proxy::Enh_DataCollectConfig_Proxy;

namespace {
[[maybe_unused]]bool RewriteAdrConfig() {
    const std::string& config_path = global_data::g_adr_yaml_config_path;
    const std::string& backup_config_path = global_data::g_adr_yaml_config_backup_path;
    YAML::Node config;
    try {
        config = YAML::LoadFile(config_path);
    } catch (const YAML::Exception& e) {
        Log_ERROR("Error loading adr config from {}", config_path);
        return false;
    }
    std::vector<std::string> sub_topics;
    try {
        Json::Reader reader;
        Json::Value root, data;
        if (!reader.parse(global_data::g_collect_config_buf, root)) {
            Log_ERROR("Error parsing config");
            return false;
        }
        data = root["data"]["topicNum"];
        for (const auto& item : data) {
            sub_topics.push_back(item["topic"].asString());
        }
    } catch (const std::exception& e) {
        Log_ERROR("Error reading sub_topic from config");
        return false;
    }
    if (sub_topics.empty()) {
        Log_ERROR("Read empty sub_topic from config");
        return false;
    }
    try {
        std::filesystem::copy_file(
            config_path,
            backup_config_path,
            std::filesystem::copy_options::overwrite_existing
        );
    } catch (const std::filesystem::filesystem_error& e) {
        Log_ERROR("Failed to back up adr config");
        return false;
    }
    try {
        YAML::Node sub_topic = config["sub_topic"];
        if (!sub_topic) {
            Log_ERROR("Adr config has no sub_topic field");
            return false;
        }
        if (!sub_topic.IsSequence()) {
            Log_ERROR("sub_topic field is not array type");
            return false;
        }
        config["sub_topic"] = sub_topics;
        std::ofstream ofs(config_path);
        ofs << config;
        ofs.close();
    } catch (const YAML::Exception& e) {
        Log_ERROR("Error rewriting adr config to {}", config_path);
        return false;
    }
    Log_Info("Successfully updating adr config");
    return true;
}
}  // namespace


CollectConfig::CollectConfig()
{
    Log_Info("run timer 3 get_config again...");
    m_timer_3 = new Timer(true); // 单次定时
    m_timer_3->Start(1000 * 60 * 3, std::bind(&CollectConfig::getConfigAgain, this));
}
CollectConfig::~CollectConfig()
{
}

CollectConfig &CollectConfig::getInstance()
{
    static CollectConfig adr;
    return adr;
}


// 拉取配置不加载
void CollectConfig::getConfigAgain()
{
    std::thread tGetConfigAgain([=]()
    {
        //获取根证书
        BusinessCaCerUpdate::getInstance().init();

        //拉云端配置
        bool bgetConfSuccess = true;

        if(getConfig() != true)
        {
            bgetConfSuccess = false;
        }
        Log_Info("getConfigAgain; bgetConfSuccess:{}", bgetConfSuccess);

        if (!global_data::g_collect_config_buf.empty() && bgetConfSuccess) 
        {
            //保存云端配置文件到本地
            std::ofstream os;
            os.open(global_data::g_config_cloud_path);
            if (!os.is_open())
            {
                Log_Info("file open failed, g_config_cloud_path : {}", global_data::g_config_cloud_path);
            }
            os << global_data::g_collect_config_buf;
            os.close();
            Log_Info("[CollectConfig] get server config success;write to:{} success", global_data::g_config_cloud_path);
#if 0
            // 更新订阅topic
            RewriteAdrConfig();
#endif
            //众包地图配置，保存到本地
            MapCollect::getInstance().saveConfig(global_data::g_collect_config_buf);          
        }
        else
        {
            Log_Info("[CollectConfig] getConfigAgain faild;");
        } 

        //加载众包地图配置(3分钟后才开始众包地图采集)
        string fencesConf;
        CommonOprSystem::readFileAllOnce(global_data::g_config_map_path, fencesConf);

        try
        {
            MapCollect::getInstance().parseMapConfigJsonData(fencesConf);
        }
        catch (const std::exception &e)
        {
            Log_ERROR("trow exception: {}", e.what());
        }

    });
    tGetConfigAgain.detach();
}

void CollectConfig::init()
{
    const char *path = nullptr;
    if (0 == access(global_data::g_config_cloud_path.c_str(), F_OK)) // 如果文件存在，就先用g_config_cloud_path路径下的配值
    {
        struct stat s_buf;
        int retCI = stat(global_data::g_config_cloud_path.c_str(), &s_buf);
        Log_Info("[CollectConfig] [init] USE_CONFIG:{};modifyTime:{} retCI:{}", global_data::g_config_cloud_path, to_string(s_buf.st_mtime), retCI);
        path = global_data::g_config_cloud_path.c_str();
    }
    else
    {
        Log_Info("[CollectConfig] [init] USE_LOCAL_CONFIG");
        path = global_data::g_config_path.c_str();
    }

    std::string ret = "";
    ifstream in(path);
    if (in)
    {
        Log_Info("first start;use_config path:{}", path);
        stringstream buffer;
        buffer << in.rdbuf();
        ret = buffer.str();
        in.close();
    }
    else
    {
        // ModifyDiagnosisSts(8);
    }

    // Log_Info("USE_CONFIG ret: {}", ret);
    global_data::g_collect_config_buf = ret;

    Log_Info("USE_CONFIG: {}", global_data::g_collect_config_buf);
}

bool CollectConfig::getConfig()
{
    Log_Info("[CollectConfig] [get_Config] get configuration from cloud");

    static uint8_t tokenTrynum = 0;
    bool bGetToken = true;

    while (!(bGetToken = m_httpCommon.httpReqInit(STR_DOMAIN_SYS)))
    {
        tokenTrynum++;

        if (15 < tokenTrynum) // zjs_tmp_0305;
        {
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }

    // CommonOprHttp 初始化
    if (!bGetToken)
    {
        Log_Info("[CollectConfig] [get_Config] Init http failed.");
        return false;
    }

    Log_Info("[CollectConfig] get_Config, m_httpCommon.hu_tokenMsg : {}", m_httpCommon.hu_tokenMsg);

    if (!m_httpCommon.hu_tokenMsg.empty())
    {
        return getConfigFromCloud();
    }

    Log_Info("[CollectConfig] [get_Config] get configuration from cloud, completed!");
    return true;
}

bool CollectConfig::getConfigFromCloud()
{
    Log_Info("[CollectConfig] [getConfigFromCloud] g_cloudConfigVersion: {}", global_data::g_cloudConfigVersion);

    std::string all_addr = SRT_HTTPSPRE + m_httpCommon.domainHost + SRT_URL_GETSDRCONFIG;
    all_addr += "&currentVersion=" + global_data::g_cloudConfigVersion;
    all_addr += "&modelType=C3B&iteration=" + global_data::g_iteration; // ADR ALL

    Log_Info("[http_url][getConfig] all_addr: {}", all_addr);

    // 设置http请求头
    map<string, string> http_header;
    http_header["Content-Type"] = "application/json;charset=UTF-8";
    http_header["Accept"] = "*/*";
    http_header["X-VCS-Hu-Token"] = m_httpCommon.hu_tokenMsg;
    http_header["X-VCS-Timestamp"] = CommonOprTime::getTimestr();
    http_header["X-VCS-Nonce"] = CommonOprString::GetRandStr(4);

    // 参考edc代码？ GetCloudConfig::getConfigFromCloud()

    std::string responseBuff;
    if (m_httpCommon.getCloudConfig(all_addr, http_header, responseBuff))
    {
        Json::Reader reader;
        Json::Value root;
        if (reader.parse(responseBuff, root) && root.isMember("data"))
        {
            global_data::g_collect_config_buf = responseBuff;
            return true;
        }
    }
    return false;
}
